import { isMod } from "../Utils";
import { Draw } from "../Draw/Draw";
import { Command } from "../Command/Command";
import { ShortCutList } from "./keys/ShortCutList";
import { IRegisterShortcut } from "../Interface/ShortCut";

export class ShortCut {
  private draw: Draw;
  private command: Command;
  private globalShortcutList: IRegisterShortcut[];

  /** 传入 command 意在所有的快捷键执行事件，都可以在 commmand 中找到事件执行，快捷键的核心事件来源于 command */
  constructor(draw: Draw) {
    this.draw = draw;

    this.command = draw.getCommand();

    this.globalShortcutList = [];

    this._addShortcutList([...ShortCutList]); // 项目默认快捷键

    this._addEvent(); // 初始化事件
  }

  private _globalKeydown = (evt: KeyboardEvent) => {
    if (!this.globalShortcutList.length) return;
    this._execute(evt, this.globalShortcutList);
  };

  /** 解决 bind this 异常问题 */
  private bindEvent = this._globalKeydown.bind(this);
  private bindKeyUpEvent = this._globalKeyup.bind(this);

  private _addEvent() {
    document.addEventListener("keydown", this.bindEvent);
    document.addEventListener("keyup", this.bindKeyUpEvent);
  }

  /** 供外部调用 - 取消事件 */
  public removeEvent() {
    document.removeEventListener("keydown", this.bindEvent);
    document.removeEventListener("keyup", this.bindKeyUpEvent);
  }

  /** 供外部调用： 添加快捷键列表 */
  public registerShortcutList(payload: IRegisterShortcut[]) {
    this._addShortcutList(payload);
  }

  /** 将快捷键列表添加到事件列表中 */
  private _addShortcutList(payload: IRegisterShortcut[]) {
    for (let s = payload.length - 1; s >= 0; s--) {
      const shortCut = payload[s];
      this.globalShortcutList.unshift(shortCut);
    }
  }

  /** document keydown 事件 */
  private _execute(evt: KeyboardEvent, shortCutList: IRegisterShortcut[]) {
    // 进行特殊处理
    if (evt.code === "Space") {
      evt.preventDefault();
      const stage = this.draw.getStage();
      stage.setAttrs({ translateMode: true });
      return;
    }
    for (let s = 0; s < shortCutList.length; s++) {
      const shortCut = shortCutList[s];
      if (
        (shortCut.mod
          ? isMod(evt) === !!shortCut.mod
          : evt.ctrlKey === !!shortCut.ctrl &&
            evt.metaKey === !!shortCut.meta) &&
        evt.shiftKey === !!shortCut.shift &&
        evt.altKey === !!shortCut.alt &&
        evt.key.toLowerCase() === shortCut.key.toLowerCase()
      ) {
        // 是否执行函数，需要根据 when 决定
        // 如果存在 when 则判真，不然都执行
        if (shortCut.when && !shortCut.when({ e: evt, draw: this.draw }))
          return;

        shortCut?.callback?.(this.command, evt);
        if (shortCut.preventDefault) evt.preventDefault();
        if (shortCut.stopPropagation) evt.stopPropagation();
        break;
      }
    }
  }

  /**
   * document keyup 事件
   *  1. 目前仅用于处理 space 抬起 取消平移状态
   */
  private _globalKeyup(evt: KeyboardEvent) {
    if (evt.code !== "Space") return;
    const stage = this.draw.getStage();
    stage.setAttrs({ translateMode: null });
  }
}
